package com.frejoys.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.payment.common.models.AlipayTradeQueryResponse;
import com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse;
import com.alipay.easysdk.payment.wap.models.AlipayTradeWapPayResponse;
import com.frejoys.common.config.AliPayProperties;
import com.frejoys.common.config.ValueConfig;
import com.frejoys.common.constant.CommonConstant;
import com.frejoys.common.enums.EOrderType;
import com.frejoys.common.error.HttpStatus;
import com.frejoys.common.exception.GeneralException;
import com.frejoys.common.response.Result;
import com.frejoys.common.util.SnowflakeUtil;
import com.frejoys.common.vo.order.AttachVo;
import com.frejoys.common.vo.pay.WxJsPayVo;
import com.frejoys.service.PayService;
import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;


@Slf4j
@Service
@RequiredArgsConstructor
public class PayServiceImpl implements PayService {

    private final WxPayService wxPayService;

    private final ValueConfig valueConfig;

    private final AliPayProperties aliPayProperties;

    @Override
    public SignatureHeader wxSignatureHeader(HttpServletRequest request) {
        // 获取通知签名
        String signature = request.getHeader("wechatpay-signature");
        String nonce = request.getHeader("wechatpay-nonce");
        String serial = request.getHeader("wechatpay-serial");
        String timestamp = request.getHeader("wechatpay-timestamp");

        SignatureHeader signatureHeader = new SignatureHeader();
        signatureHeader.setSignature(signature);
        signatureHeader.setNonce(nonce);
        signatureHeader.setSerial(serial);
        signatureHeader.setTimeStamp(timestamp);
        return signatureHeader;
    }

    @Override
    public WxJsPayVo wxJsPay(String domain, String description, String openid, String orderSn, Integer price, String currency, String attach) {

        WxJsPayVo payVo = null;

        try {

            WxPayConfig payConfig = wxPayService.getConfig();

            WxPayUnifiedOrderV3Request v3Request = new WxPayUnifiedOrderV3Request();
            v3Request.setAppid(payConfig.getAppId());
            v3Request.setMchid(payConfig.getMchId());
            v3Request.setNotifyUrl(domain + payConfig.getNotifyUrl());
            v3Request.setDescription(description);
            v3Request.setOutTradeNo(orderSn);

            if (StrUtil.isNotEmpty(attach)) {
                v3Request.setAttach(attach);
            }

            WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
            amount.setTotal(price);
            amount.setCurrency(currency);
            v3Request.setAmount(amount);

            // 订单有效时间
            Date afterDate = DateUtil.offset(DateUtil.date(), DateField.SECOND, CommonConstant.orderTimeout);
            v3Request.setTimeExpire(DateUtil.format(afterDate, "yyyy-MM-dd'T'HH:mm:ssXXX"));

            WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
            payer.setOpenid(openid);
            v3Request.setPayer(payer);

            WxPayUnifiedOrderV3Result result = wxPayService.unifiedOrderV3(TradeTypeEnum.JSAPI, v3Request);

            WxPayUnifiedOrderV3Result.JsapiResult jsapiResult = result.getPayInfo(TradeTypeEnum.JSAPI, payConfig.getAppId(), payConfig.getMchId(), payConfig.getPrivateKey());

            if (jsapiResult != null) {
                payVo = new WxJsPayVo();
                payVo.setAppId(jsapiResult.getAppId());
                payVo.setTimeStamp(jsapiResult.getTimeStamp());
                payVo.setNonceStr(jsapiResult.getNonceStr());
                payVo.setPackageValue(jsapiResult.getPackageValue());
                payVo.setSignType(jsapiResult.getSignType());
                payVo.setPaySign(jsapiResult.getPaySign());
            }

        } catch (WxPayException e) {
            // e.printStackTrace();
            log.error("微信jsapi支付错误: ", e);
            // System.out.println("微信jsapi支付错误: " + e.getMessage());
            throw new GeneralException(HttpStatus.wechatPayError);
        }

        return payVo;
    }

    @Override
    public WxJsPayVo wxH5Pay(String domain, String description, String openid, String orderSn, Integer price, String currency, String attach) {
        try {

            WxPayConfig payConfig = wxPayService.getConfig();

            WxPayUnifiedOrderV3Request v3Request = new WxPayUnifiedOrderV3Request();
            v3Request.setAppid(payConfig.getAppId());
            v3Request.setMchid(payConfig.getMchId());
            v3Request.setNotifyUrl(domain + payConfig.getNotifyUrl());
            v3Request.setDescription(description);
            v3Request.setOutTradeNo(orderSn);

            WxPayUnifiedOrderV3Request.SceneInfo sceneInfo = new WxPayUnifiedOrderV3Request.SceneInfo();
            sceneInfo.setPayerClientIp(NetUtil.getLocalhostStr());
            WxPayUnifiedOrderV3Request.H5Info h5Info = new WxPayUnifiedOrderV3Request.H5Info();
            h5Info.setType("Wap");
            sceneInfo.setH5Info(h5Info);
            v3Request.setSceneInfo(sceneInfo);

            if (StrUtil.isNotEmpty(attach)) {
                v3Request.setAttach(attach);
            }

            WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
            amount.setTotal(price);
            amount.setCurrency(currency);
            v3Request.setAmount(amount);

            // 订单5分钟有效
            Date afterDate = DateUtil.offset(DateUtil.date(), DateField.SECOND, CommonConstant.orderTimeout);
            v3Request.setTimeExpire(DateUtil.format(afterDate, "yyyy-MM-dd'T'HH:mm:ssXXX"));

            // WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
            // payer.setOpenid(openid);
            // v3Request.setPayer(payer);

            WxPayUnifiedOrderV3Result result = wxPayService.unifiedOrderV3(TradeTypeEnum.H5, v3Request);

            System.out.println(result);
            // WxPayUnifiedOrderV3Result.JsapiResult jsapiResult = result.getPayInfo(TradeTypeEnum.JSAPI, payConfig.getAppId(), payConfig.getMchId(), payConfig.getPrivateKey());
            //
            // if (jsapiResult != null) {
            //     payVo = new WxJsPayVo();
            //     payVo.setAppId(jsapiResult.getAppId());
            //     payVo.setTimeStamp(jsapiResult.getTimeStamp());
            //     payVo.setNonceStr(jsapiResult.getNonceStr());
            //     payVo.setPackageValue(jsapiResult.getPackageValue());
            //     payVo.setSignType(jsapiResult.getSignType());
            //     payVo.setPaySign(jsapiResult.getPaySign());
            // }

        } catch (WxPayException e) {
            // e.printStackTrace();
            log.error("微信H5支付错误: ", e);
            // System.out.println("微信H5支付错误: " + e.getMessage());
            throw new GeneralException(HttpStatus.wechatPayError);
        }

        return null;
    }

    @Override
    public Boolean wxRefund(String domain, String orderSn, Integer price, String currency) {

        WxPayConfig payConfig = wxPayService.getConfig();
        WxPayRefundV3Request request = new WxPayRefundV3Request();

        WxPayRefundV3Request.Amount am = new WxPayRefundV3Request.Amount();

        am.setTotal(price);
        am.setCurrency(currency);
        am.setRefund(price);

        request.setAmount(am);
        request.setOutTradeNo(orderSn);
        request.setOutRefundNo(orderSn);
        request.setNotifyUrl(domain + payConfig.getPayScoreNotifyUrl());

        try {
            WxPayRefundV3Result v3Result = wxPayService.refundV3(request);
            if (v3Result != null) {
                return v3Result.getStatus().equals("SUCCESS");
            }

        } catch (WxPayException e) {
            // e.printStackTrace();
            log.error("微信退款失败: ", e);
            // System.out.println("微信退款失败: " + e.getMessage());
        }

        throw new GeneralException(HttpStatus.orderRefundWxPayError);
    }

    @Override
    public WxPayOrderQueryV3Result wxOrderInfo(String orderSn) {
        try {
            WxPayOrderQueryV3Request v3Request = new WxPayOrderQueryV3Request();
            v3Request.setMchid(wxPayService.getConfig().getMchId());
            v3Request.setOutTradeNo(orderSn);
            return wxPayService.queryOrderV3(v3Request);
        } catch (WxPayException e) {
            // e.printStackTrace();
            log.error("微信查询订单失败: ", e);
            // System.out.println("微信查询订单失败: " + e.getMessage());
        }
        throw new GeneralException(HttpStatus.orderWechatSelectError);
    }

    @Override
    public Boolean wxOrderPayResult(String orderSn) {
        WxPayOrderQueryV3Result v3Result = wxOrderInfo(orderSn);
        if (v3Result != null) {
            return v3Result.getTradeState().equals("SUCCESS");
        }
        return false;
    }

    @Override
    public Boolean wxTransferWallet(String openid, Long orderSn, Integer money, String desc) {
        WxPayConfig payConfig = wxPayService.getConfig();

        // if (null == null) {
        //     System.out.println(payConfig.getAppId());
        //     return true;
        // }

        try {
            EntPayRequest entPayRequest = new EntPayRequest();
            entPayRequest.setAppid(payConfig.getAppId());
            entPayRequest.setMchId(payConfig.getMchId());
            entPayRequest.setOpenid(openid);
            entPayRequest.setCheckName("NO_CHECK");
            entPayRequest.setPartnerTradeNo(String.valueOf(orderSn));
            entPayRequest.setAmount(money);
            entPayRequest.setDescription(desc);
            entPayRequest.setSpbillCreateIp(NetUtil.getLocalhostStr());

            EntPayResult entPayResult = wxPayService.getEntPayService().entPay(entPayRequest);
            System.out.println("--------------------------------");
            System.out.println(entPayResult);
            if (entPayResult.getResultCode().equals(CommonConstant.SUCCESS)) {

            }


            return true;
        } catch (WxPayException e) {
            // e.printStackTrace();
            log.error("微信转账失败: ", e);
        }

        return false;
    }


    @Override
    public String aliH5Pay(String domain, String description, String orderSn, String price, String attach) {

        Map<String, Object> optionalArgs = new HashMap<>();
        optionalArgs.put("body", attach);
        optionalArgs.put("timeout_express", "10m");

        try {
            // AlipayTradeWapPayResponse response = Factory.Payment.Wap().batchOptional(optionalArgs).pay(description, orderSn, price, domain, domain + aliPayProperties.getReturnUrl());

            AlipayTradeWapPayResponse response = Factory.Payment.Wap().batchOptional(optionalArgs).pay(description, orderSn, price, domain, domain);

            return response.body;
        } catch (Exception e) {
            // e.printStackTrace();
            log.error("支付宝H5支付失败: ", e);
        }

        return null;
    }

    @Override
    public Boolean aliRefund(String orderSn, String price) {
        try {
            AlipayTradeRefundResponse response = Factory.Payment.Common().refund(orderSn, price);

            if (response != null && StrUtil.isNotEmpty(response.getHttpBody())) {
                JSONObject jsonObject = JSONUtil.parseObj(response.getHttpBody());

                if (jsonObject.getJSONObject("alipay_trade_refund_response").get("code").equals("10000")) {
                    return true;
                } else if (jsonObject.getJSONObject("alipay_trade_refund_response").get("code").equals("40004")) {
                    return true;
                }

            }

        } catch (Exception e) {
            // e.printStackTrace();
            log.error("支付宝退款失败: ", e);
        }

        throw new GeneralException(HttpStatus.orderRefundAliPayError);
    }

    @Override
    public AlipayTradeQueryResponse aliOrderInfo(String orderSn) {
        try {
            return Factory.Payment.Common().query(orderSn);
        } catch (Exception e) {
            // e.printStackTrace();
            log.error("支付宝获取订单信息失败: ", e);
        }
        throw new GeneralException(HttpStatus.orderAlipaySelectError);
    }

    @Override
    public Boolean aliOrderPayResult(String orderSn) {
        AlipayTradeQueryResponse query = aliOrderInfo(orderSn);

        if (StrUtil.isNotEmpty(query.getHttpBody())) {
            JSONObject jsonObject = JSONUtil.parseObj(query.getHttpBody());
            try {
                if (jsonObject.getJSONObject("alipay_trade_query_response").get("code").equals("10000") && jsonObject.getJSONObject("alipay_trade_query_response").get("trade_status").equals("TRADE_SUCCESS")) {
                    return true;
                }
            } catch (Exception e) {
                // e.printStackTrace();
                log.error("支付宝订单支付结果查询失败: ", e);
            }
        }

        return false;
    }


}
